﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Thor.Configuration;
using Thor.Domain;

namespace Thor.Domain
{
    public class InvalidLogonHelper
    {
        #region fields

        private static ConfigurationSettings _ConfigSettings = new ConfigurationSettings();
        private static string _ApplicationNameKey = ConfigurationSettings.ApplicationNameKey;
        private static string _ApplicationNameValue = ConfigurationSettings.ApplicationNameValue;
        private static string _ConnectionStringKey = ConfigurationSettings.ConnectionStringKey;
        private static string _ConnectionStringValue = ConfigurationSettings.ConnectionStringValue;
        private static string _RepositoryAssembly = AppDomain.CurrentDomain.BaseDirectory + ConfigurationSettings.InvalidLogonRepositoryAssembly;
        private static string _RepositoryType = ConfigurationSettings.InvalidLogonRepositoryType;

        #endregion

        #region constructors

        private InvalidLogonHelper() { }

        #endregion

        #region properties

        private static ConfigurationSettings ConfigurationSettings
        {
            get
            {
                if (_ConfigSettings == null)
                    _ConfigSettings = new ConfigurationSettings();

                return _ConfigSettings;
            }
        }

        public static IInvalidLogonRepository Repository
        {
            get
            {
                Dictionary<string, object> parameters = GetRepositoryParameters();
                return GetRepository(parameters);
            }
        }

        #endregion

        #region methods

        private static Dictionary<string, object> GetRepositoryParameters()
        {
            Dictionary<string, object> parameters = new Dictionary<string, object>();
            parameters.Add(_ApplicationNameKey, _ApplicationNameValue);
            parameters.Add(_ConnectionStringKey, _ConnectionStringValue);
            return parameters;
        }

        private static IInvalidLogonRepository GetRepository(Dictionary<string, object> parameters)
        {
            return InvalidLogonManager.GetRepository(_RepositoryAssembly, _RepositoryType, parameters);
        }

        public static InvalidLogonManager GetManager()
        {
            Dictionary<string, object> parameters = GetRepositoryParameters();
            IInvalidLogonRepository repository = GetRepository(parameters);
            InvalidLogonManager manager = new InvalidLogonManager(repository);
            return manager;
        }

        public static bool IsLogonLocked(string userName)
        {
            InvalidLogon logon = GetManager().GetInvalidLogon(userName);

            if (logon != null)
            {
                var retryCount = SettingsHelper.GetSettings().RetryCount;
                var lockoutDuration = SettingsHelper.GetSettings().LockoutDuration;

                if (retryCount > 0 && lockoutDuration > 0)
                {
                    if (logon.AttemptCount >= retryCount)
                    {
                        DateTime lockOutEnd = logon.LastAttemptTimestamp.AddMinutes(lockoutDuration);

                        if (DateTime.UtcNow < lockOutEnd)
                        {
                            return true;
                        }
                    }
                }

                return false;
            }

            return false;
        }

        public static void Update(string userName)
        {
            InvalidLogon logon = GetManager().GetInvalidLogon(userName);
            DateTime timestamp = DateTime.UtcNow;

            if (logon == null)
            {
                logon = new InvalidLogon();
                logon.UserName = userName;
                logon.AttemptCount = 1;
                logon.FirstAttemptTimestamp = timestamp;
                logon.LastAttemptTimestamp = timestamp;

                GetManager().Insert(logon);
            }
            else
            {
                logon.AttemptCount += 1;
                logon.LastAttemptTimestamp = timestamp;

                GetManager().Update(logon);
            }
        }

        #endregion
    }
}
